<script setup lang="ts">
import { Node, Edge, GraphNode, MouseTouchEvent, NodeChange } from '@vue-flow/core'

type FlowPropsType = {
  nodeClick?: (node: GraphNode, event: MouseTouchEvent) => void
  nodeMouseEnter?: (node: GraphNode, event: MouseTouchEvent) => void
  nodeMouseLeave?: (node: GraphNode, event: MouseTouchEvent) => void
  nodeMouseMove?: (node: GraphNode, event: MouseTouchEvent) => void
  nodeDrag?: (node: GraphNode, nodes: GraphNode[], event: MouseTouchEvent) => void
  nodeRemove?: (ids: string[]) => void
  connect?: (
    source: string,
    target: string,
    sourceHandle: string | null | undefined,
    targetHandle: string | null | undefined
  ) => void
  nodes?: Node[]
  'onUpdate:nodes'?: (nodes: Node[]) => void
  edges?: Edge[]
  'onUpdate:edges'?: (edges: Edge[]) => void
}

import { VueFlow, useVueFlow } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import '@vue-flow/core/dist/style.css'
import '@vue-flow/core/dist/theme-default.css'

defineOptions({
  name: 'SFlow'
})

const props = withDefaults(defineProps<FlowPropsType>(), {
  nodeClick: () => {},
  nodeMouseEnter: () => {},
  nodeMouseLeave: () => {},
  nodeMouseMove: () => {},
  nodeDrag: () => {},
  nodeRemove: () => {},
  connect: () => {}
})

const nodes = defineModel<Node[]>('nodes', { default: [] })
const edges = defineModel<Edge[]>('edges', { default: [] })

const {
  onNodeClick,
  onNodeMouseEnter,
  onNodeMouseLeave,
  onNodeMouseMove,
  onNodeDrag,
  onNodesChange,
  onConnect
} = useVueFlow()

onNodeClick(({ event, node }) => {
  props.nodeClick(node, event)
})
onNodeMouseEnter(({ event, node }) => {
  node.data.isShowHandle = true
  props.nodeMouseEnter(node, event)
})
onNodeMouseLeave(({ event, node }) => {
  node.data.isShowHandle = false
  props.nodeMouseLeave(node, event)
})
onNodeMouseMove(({ event, node }) => {
  node.data.isShowHandle = true
  props.nodeMouseMove(node, event)
})
onNodeDrag(({ event, node, nodes }) => {
  node.data.isShowHandle = false
  props.nodeDrag(node, nodes, event)
})
onNodesChange((nodeChanges: NodeChange[]) => {
  const nodeIdsRemove: string[] = []
  for (const nodeChange of nodeChanges) {
    if (nodeChange.type === 'remove') nodeIdsRemove.push(nodeChange.id)
  }
  if (nodeIdsRemove.length > 0) props.nodeRemove(nodeIdsRemove)
})

onConnect(({ source, target, sourceHandle, targetHandle }) => {
  props.connect(source, target, sourceHandle, targetHandle)
})
</script>

<template>
  <vue-flow :nodes="nodes" :edges="edges">
    <template #node-exec="node">
      <!--<NodeResizer :min-width="100" :min-height="30" />-->
      <s-node-handle-round-source :show="node.data.isShowHandle" :color="node.data.color">
        <s-node-gradient-dynamic-border :color="node.data.color">
          {{ node.data.label }}
        </s-node-gradient-dynamic-border>
      </s-node-handle-round-source>
    </template>
    <Background />
  </vue-flow>
</template>

<style scoped lang="scss"></style>
